其他
如何做慢SQL治理?
凌云时刻
编者按:慢SQL治理进入日常化,本文作者从策略制定、问题分析、解决过程等方面与大家交流分享下。
为什么要做这个事情
# 查看慢SQL是否开启
show variables like "slow_query_log%";
# 查看慢查询设定的阈值 单位:秒
show variables like "long_query_time";
要做到什么程度
sum(aone应用慢SQL执行次数)
-----------------------
sum(aone应用SQL执行次数)
宏平均
sum(慢SQL 1执行次数) sum(慢SQL n执行次数)
----------------- + ------------------
sum(SQL 1执行次数) sum(SQL n执行次数)
---------------------------------------
n
执行次数
sum(aone应用慢SQL执行次数)
-----------------------
7
慢SQL模板数量
count(distinct(aone应用慢SQL模板) )
核心应用:解决掉所有的慢SQL 普通应用:微平均指标下降50%
为什么由我来做
行动支撑
【强制】在varchar字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度。
【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。
【推荐】防止因字段类型不同造成的隐式转换,导致索引失效。
【参考】创建索引时避免有如下极端误解:
分享一些我参与优化的例子
SELECT
COUNT(0) AS `tmp_count`
FROM(
SELECT
`table_holder`.`user_id`,
`table_holder`.`sc_item_id`,
SUM(
CASE
`table_holder`.`inventory_type`
WHEN 1 THEN `table_holder`.`quantity`
ELSE 0
END
) AS `saleable_quantity`,
SUM(
CASE
`table_holder`.`inventory_type`
WHEN 1 THEN `table_holder`.`lock_quantity`
ELSE 0
END
) AS `saleable_lock_quantity`,
SUM(
CASE
`table_holder`.`inventory_type`
WHEN 401 THEN `table_holder`.`quantity`
ELSE 0
END
) AS `transfer_on_way_quantity`,
`table_holder`.`store_code`,
MAX(`table_holder`.`gmt_modified`) AS `gmt_modified`
FROM
`table_holder`
WHERE(`table_holder`.`is_deleted` = 0)
AND(`table_holder`.`quantity` > 0)
AND `table_holder`.`user_id` IN(3405569954)
AND `table_holder`.`store_code` IN('ZJJHBHYTJJ0001', '...1000多个')
GROUP BY
`table_holder`.`user_id`,
`table_holder`.`sc_item_id`
ORDER BY
`table_holder`.`user_id` ASC,
`table_holder`.`sc_item_id` ASC
) `a`;
char(10)允许NULL = 10 * ( character set:utf8mb4=4,utf8=3,gbk=2,latin1=1) + 1(NULL)
char(10)不允许NULL = 10 * ( character set:utf8mb4=4,utf8=3,gbk=2,latin1=1)
varchr(10)允许NULL = 10 * ( character set:utf8mb4=4,utf8=3,gbk=2,latin1=1) + 1(NULL) + 2(变长字段)
varchr(10)不允许NULL = 10 * ( character set:utf8mb4=4,utf8=3,gbk=2,latin1=1) + 2(变长字段)
int允许NULL = 4 + 1(NULL)
int不允许NULL = 4
timestamp允许NULL = 4 + 1(NULL)
timestamp不允许NULL = 4
datatime允许NULL = 5 + 1(NULL)
datatime不允许NULL = 5
用到了索引却依然被爆出扫描2千万行:
排查共用物理机其他实例的情况,发现有个库在问题时间附近有很多慢sql需要排序,写临时文件刚好写入了2GB:
多个MySQL实例leader节点混合部署在同一台物理机,虽然通过docker隔离了CPU、MEM等资源,但目前还没有做到buffer io的隔离。
通过汇总分析高频的查询并结合业务得出合适的索引往往能够解决日常遇到的慢查询,但这并不是万能的。
比如有可能索引越加越多,乃至成了这样:
有些场景,比如支持多个字段组合查询,又没有必填项,如果都要通过索引来支持显然是不合理的。
查询场景下,将区分度较高的字段设定为必填项是个好习惯;查询组合很多的情况下考虑走搜索支持性更好的存储或者搜索引擎。
日常化处理
你可能还想看
1. 对话阿里云飞刀:数据库迎来开源新时代
2. 进入“后红海”时代,大数据体系到底是什么?
3. 阿里云工程师带你去东京看奥运
4. 直播时各种背景原来是这样实现的!
5. dubbogo PMC何鑫铭:没有热爱就做不成这件事情
END
关注「凌云时刻」并设置星标✨精彩推送不错过✨